package com.shop.aop;

import com.shop.annotation.RequireRoles;
import com.shop.model.vo.Rsp;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @BelongsProject: shop
 * @BelongsPackage: com.shop.aop
 * @Author: GaoDo
 * @CreateTime: 2020-11-22 21:13
 * @Description:    鉴权AOP,整合日志
 */
@Aspect
@Component
@Order(-100)
public class AuthAspect{
//    @Autowired
//    @Qualifier("restHighLevelClient")
//    private RestHighLevelClient client;
    //日志记录白名单
    private static List<String> whiteLogList ;
    static{
        String [] str={"/getLog","/getRequest"};
        whiteLogList= Arrays.asList(str);
    }

    private static Logger log = LoggerFactory.getLogger(AuthAspect.class);

    //设置切点 类型是一个方法体为空 无返回值 的方法  传入注解对象为参数
    @Pointcut("@annotation(requireRoles)")
    public void AuthService(RequireRoles requireRoles){}

    //切面处理方法 采用环绕型通知方法 传入上面配置的切点信息
    @Around("AuthService(requireRoles)")
    public Object doAroud(ProceedingJoinPoint joinPoint, RequireRoles requireRoles) throws Throwable {
        //从请求头中取出roleSign
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();
        String roleSign=(String) request.getHeader("roleSign");
        //获取我们注解中配置的角色信息 返回的是roleSign数组
        String [] roles = requireRoles.roles();
        //获取被拦截方法的参数
        if(Arrays.asList(roles).contains(roleSign)){
            //如果注解中的角色id包含 这次请求中角色的id  就放行 继续执行后面的操作
            return joinPoint.proceed();
        }else{
            //如果不包含 则返回权限不足的错误提示
            return Rsp.fail().msg("权限不足");
        }
    }

}
